//
//  MapViewController.swift
//  LocationDemo
//
//  Created by HzS on 2023/2/4.
//

import UIKit
import MapKit

class MapViewController: UIViewController {
    
    @IBOutlet weak var mapView: MKMapView!
    private var lastPolyline: MKPolyline?
    
    private var currentDate = Date()
    private lazy var calendar: Calendar = {
        var calendar = Calendar(identifier: .gregorian)
        calendar.timeZone = TimeZone(identifier: "Asia/Shanghai")!
        return calendar
    }()

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
        setupUI()
        loadData()
    }
    
    private func setupUI() {
        let rightItem = UIBarButtonItem(title: "路径日期", style: .plain, target: self, action: #selector(handleRightBarButtonItemClick(_:)))
        navigationItem.rightBarButtonItem = rightItem
        
        mapView.userTrackingMode = .none
        mapView.showsUserLocation = true
    }
    
    private func loadData() {
        let formatter = DateFormatter()
        formatter.dateFormat = "yyyy-M-d"
        title = formatter.string(from: currentDate)
        
        if let lastPolyline {
            mapView.removeOverlay(lastPolyline)
        }
        
        guard let timestampRange = timestampRange(for: currentDate) else { return }
        let locations = LocationManager.shared.database.getHistoryLocations(startTimestamp: timestampRange.0, endTimestamp: timestampRange.1)
        if locations.isEmpty { return }
        
        var coordinates = locations.map({ $0.coordinate })
        let polyLine = MKPolyline(coordinates: &coordinates, count: coordinates.count)
        lastPolyline = polyLine
        mapView.addOverlay(polyLine)
        
        
        let span = MKCoordinateSpan(latitudeDelta: 0.02, longitudeDelta: 0.02)
        let region = MKCoordinateRegion(center: locations[0].coordinate, span: span)
        let rect = MKMapRectForCoordinateRegion(region: region)
        // Adjust padding here
        let insets = UIEdgeInsets(top: 0, left: 0, bottom: 150, right: 0)
        self.mapView?.setVisibleMapRect(rect, edgePadding: insets, animated: false)
    }
    
    @objc
    private func handleRightBarButtonItemClick(_ sender: UIBarButtonItem) {
        let alert = UIAlertController(title: "请选择查看日期", message: nil, preferredStyle: .actionSheet)
        let beforeAction = UIAlertAction(title: "前一天", style: .default) { (_) in
            self.currentDate = self.currentDate.dateByAddingDays(-1)!
            self.loadData()
        }
        alert.addAction(beforeAction)
        let nextAction = UIAlertAction(title: "后一天", style: .default) { (_) in
            self.currentDate = self.currentDate.dateByAddingDays(1)!
            self.loadData()
        }
        alert.addAction(nextAction)
        
        let cancel = UIAlertAction(title: "取消", style: .cancel)
        alert.addAction(cancel)
    
        present(alert, animated: true, completion: nil)
    }

}

extension MapViewController: MKMapViewDelegate {
    func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
        let polyLineRender = PoPolylineAndPointRender(overlay: overlay)
        polyLineRender.strokeColor = UIColor.blue
        polyLineRender.lineWidth = 3
        return polyLineRender
    }
}

extension MapViewController {
    func getTimestamp(date: Date, hour: Int, minute: Int, seconds: Int) -> Int? {
        let dateComponents = calendar.dateComponents([.year, .month, .day], from: date)
        
        var dateComponentsForDate = DateComponents()
        dateComponentsForDate.year = dateComponents.year
        dateComponentsForDate.month = dateComponents.month
        dateComponentsForDate.day = dateComponents.day
        dateComponentsForDate.hour = hour
        dateComponentsForDate.minute = minute
        dateComponentsForDate.second = seconds
        
        guard let newDate = calendar.date(from: dateComponentsForDate) else { return nil }
        return Int(newDate.timeIntervalSince1970 * 1000)
    }
    
    func timestampRange(for date: Date) -> (Int, Int)? {
        if let startTimestamp = getTimestamp(date: date, hour: 0, minute: 0, seconds: 0),
           let endTimestamp = getTimestamp(date: date, hour: 23, minute: 59, seconds: 59) {
            return (startTimestamp, endTimestamp)
        }
        return nil
    }
}

// Convert CoordinateRegion to MapRect
func MKMapRectForCoordinateRegion(region:MKCoordinateRegion) -> MKMapRect {
    let topLeft = CLLocationCoordinate2D(latitude: region.center.latitude + (region.span.latitudeDelta/2), longitude: region.center.longitude - (region.span.longitudeDelta/2))
    let bottomRight = CLLocationCoordinate2D(latitude: region.center.latitude - (region.span.latitudeDelta/2), longitude: region.center.longitude + (region.span.longitudeDelta/2))

    let a = MKMapPoint(topLeft)
    let b = MKMapPoint(bottomRight)

    return MKMapRect(origin: MKMapPoint(x:min(a.x,b.x), y:min(a.y,b.y)), size: MKMapSize(width: abs(a.x-b.x), height: abs(a.y-b.y)))
}

class PoPolylineAndPointRender: MKPolylineRenderer {
    
    var pointColor: UIColor = .red
    var pointRadius: CGFloat = 4
    
    override func draw(_ mapRect: MKMapRect, zoomScale: MKZoomScale, in context: CGContext) {
        super.draw(mapRect, zoomScale: zoomScale, in: context)
        
        let pointsRect = self.path.boundingBox
        let mapRectCG = rect(for: mapRect)
        if !mapRectCG.intersects(pointsRect) { return }
        
        let pointCount = polyline.pointCount
        let points = polyline.points()
        
        let width = context.convertToUserSpace(CGSize(width: pointRadius, height: pointRadius)).width
        for i in 0..<pointCount {
            let mapPoint = points.advanced(by: i).pointee
            let point = point(for: mapPoint)
            context.move(to: point)
            context.addEllipse(in: CGRect(x: point.x - width, y: point.y - width, width: 2*width, height: 2*width))
            context.setFillColor(pointColor.cgColor)
            context.fillPath()
        }
    }
}
